package org.openmrs.web.controller.user;

import java.io.StringReader;
import java.io.StringWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.jfree.util.Log;
import org.openmrs.Policy;
import org.openmrs.api.context.Context;
import org.openmrs.propertyeditor.PolicyEditor;
import org.openmrs.util.ExternalServiceHandler;
import org.openmrs.web.WebConstants;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.multipart.support.StringMultipartFileEditor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.xml.transform.StringSource;
import org.xacmlauth.core.domain.PolicyInfo;
import org.xacmlauth.core.domain.RegisterPolicyRequest;
import org.xacmlauth.core.domain.RegisterPolicyResponse;
import org.xacmlauth.core.policy.PolicySetType;
import org.xacmlauth.core.policy.PolicyType;
import org.xacmlauth.util.ContextManager;

public class PolicyFormController extends SimpleFormController {
	
	protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
		super.initBinder(request, binder);
		binder.registerCustomEditor(Policy.class, new PolicyEditor());
		binder.registerCustomEditor(String.class, new StringMultipartFileEditor());
	}
	
	protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object obj,
	        BindException errors) throws Exception {
		
		HttpSession httpSession = request.getSession();
		MessageSourceAccessor msa = getMessageSourceAccessor();
		
		if (Context.isAuthenticated()) {
			Policy policy = (Policy) obj;
			
			RegisterPolicyRequest registerRequest = new RegisterPolicyRequest();
			PolicyInfo policyInfo = new PolicyInfo();
			policyInfo.setClientID("20");
			policyInfo.setName(policy.getName());
			policyInfo.setDescription(policy.getDescription());
			
			JAXBContext policyContext = ContextManager.getPolicyContext();
			Unmarshaller policyUnmarshaller = policyContext.createUnmarshaller();
			
			boolean isValidPolicyContent = false;
			
			try {
				JAXBElement<?> policyRequest = (JAXBElement<?>) policyUnmarshaller.unmarshal(new StringReader(policy
				        .getContent()));
				
				Object policyObject = policyRequest.getValue();
				
				if (policyObject instanceof PolicyType) {
					policyInfo.setPolicy((PolicyType) policyObject);
					isValidPolicyContent = true;
				} else if (policyObject instanceof PolicySetType) {
					policyInfo.setPolicySet((PolicySetType) policyObject);
					isValidPolicyContent = true;
				}
			}
			catch (Exception e) {
				Log.error("Invalid policy content recieved ", e);
			}
			
			String responseMsg = null;
			if (isValidPolicyContent) {
				registerRequest.setPolicyInfo(policyInfo);
				
				JAXBContext domainContext = ContextManager.getDomainContext();
				Marshaller marshaller = domainContext.createMarshaller();
				
				StringWriter writer = new StringWriter();
				marshaller.marshal(registerRequest, writer);
				String registerContent = writer.toString();
				
				ExternalServiceHandler serviceHandler = ExternalServiceHandler.getInstance();
				String registerResponse = serviceHandler.callService(registerContent);
				
				Unmarshaller domainUnmarshaller = domainContext.createUnmarshaller();
				Object object = domainUnmarshaller.unmarshal(new StringSource(registerResponse));
				RegisterPolicyResponse policyResponse = (RegisterPolicyResponse) object;
				
				if (policyResponse.isStatus()) {
					responseMsg = msa.getMessage("Policy.savedSuccessfully");
					httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, responseMsg);
				} else {
					responseMsg = msa.getMessage("Policy.saveFailed");
					httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, responseMsg);
				}
			} else {
				responseMsg = msa.getMessage("Policy.invalidContent");
				httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, responseMsg);
			}
		}
		
		String view = getSuccessView();
		return new ModelAndView(new RedirectView(view));
	}
	
	protected Object formBackingObject(HttpServletRequest request) throws ServletException {
		Policy policy = new Policy();
		return policy;
	}
	
}
